package org.topteam.oschat.socket;

import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.List;
import java.util.Map;

import javax.websocket.CloseReason;
import javax.websocket.OnClose;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.ServerEndpoint;

import org.topteam.oschat.Oschat;
import org.topteam.oschat.entity.User;
import org.topteam.oschat.event.Event;
import org.topteam.oschat.event.SessionEvent;
import org.topteam.oschat.event.UserEvent.Firends;
import org.topteam.oschat.message.Data;
import org.topteam.oschat.message.TextMessage;
import org.topteam.oschat.service.IAuthService;
import org.topteam.oschat.service.IUserService;
import org.topteam.oschat.util.SpringUtils;

import akka.actor.ActorRef;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;

@ServerEndpoint(value = "/chat", decoders = { Event.Coder.class }, encoders = { Event.Coder.class })
public class WebSocketEndpoint {

	private ActorRef sessionActor;

	private IAuthService authService;
	private IUserService userService;

	private String userId;

	private String with;

	public WebSocketEndpoint() {
		sessionActor = Oschat.getInstance().getSessionActor();

		authService = SpringUtils.getBean(IAuthService.class);
		userService = SpringUtils.getBean(IUserService.class);
	}

	@OnOpen
	public void myOnOpen(Session session) {

		Map<String, List<String>> params = session.getRequestParameterMap();
		String token = params.get("token") == null ? null : params.get("token")
				.get(0);
		with = params.get("with") == null ? null : params.get("with").get(0);
		if (token != null && authService.getToken(token) != null) {
			userId = authService.getToken(token);
			System.out.println("WebSocket opened: " + userId + "["
					+ session.getId() + "]");

			User user = userService.getUser(userId);

			with = with == null ? userId : with;
			sessionActor.tell(
					new SessionEvent.SessionOpen(user, with, session),
					sessionActor);
		} else {
			try {
				session.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}

	}

	@OnMessage
	public void myOnMessage(String txt, Session session) {
		// System.out.println("WebSocket received message: " + txt);
		// Data<TextMessage> data = Data.buildTextMessage(txt, "1", "2");
		// sessionActor.tell(data.getData(), sessionActor);
		Data<?> data = JSON.parseObject(txt, Data.class);
		if (data.getType().equals("event")) {
			JSONObject t = (JSONObject) data.getData();
			String eventType = t.getString("type");
			if (eventType.equals("GetFirends")) {
				Firends firends = new Firends();
				firends.setFirends(userService.getFriends(userId));
				session.getAsyncRemote().sendObject(
						Data.buildEventMessage(firends));
			}
		} else if (data.getType().equals("textMsg")) {
			JSONObject t = (JSONObject) data.getData();
			TextMessage message = JSON.parseObject(t.toJSONString(), TextMessage.class);
			sessionActor.tell(message, sessionActor);
			session.getAsyncRemote().sendObject(data);
		}
	}

	@OnMessage
	public void myOnMessage(ByteBuffer buffer, Session session) {
		System.out.println("WebSocket received message: " + buffer);
	}

	@OnClose
	public void myOnClose(CloseReason reason, Session session) {
		System.out.println("Closing a WebSocket due to");
		sessionActor.tell(new SessionEvent.SessionClose(userId, with, session),
				sessionActor);
	}

}
